widget: Clip redrawn area to widget clip
authorTimm Bäder <mail@baedert.org>
Tue, 16 Jan 2018 19:25:02 +0000 (20:25 +0100)
committerTimm Bäder <mail@baedert.org>
Wed, 17 Jan 2018 20:57:19 +0000 (21:57 +0100)
The clip can already be modified in size_allocate, so we never want a
widget to invalidate more than its actual clip region.

gtk/gtkwidget.c

index 9c8218cfeebb68249093945df49ddb2ecbdfbdf0..2f1219925a280a8ef32b1e9efa884542d2de096f 100644 (file)
@@ -4405,6 +4405,8 @@ gtk_widget_queue_draw_region (GtkWidget            *widget,
                               const cairo_region_t *region)
 {
   GtkWidget *windowed_parent;
+  cairo_rectangle_int_t self_clip;
+  cairo_region_t *clip_region = NULL;
   cairo_region_t *region2;
   int x, y;
   GtkCssStyle *parent_style;
@@ -4419,7 +4421,6 @@ gtk_widget_queue_draw_region (GtkWidget            *widget,
   if (!_gtk_widget_get_mapped (widget))
     return;
 
-
   if (!_gtk_widget_get_parent (widget))
     {
       g_assert (_gtk_widget_get_has_window (widget));
@@ -4428,6 +4429,15 @@ gtk_widget_queue_draw_region (GtkWidget            *widget,
       goto invalidate;
     }
 
+  /* priv->clip is in parent coordinates, transform it to @widget coordinates. */
+  self_clip = widget->priv->clip;
+  self_clip.x -= widget->priv->allocation.x;
+  self_clip.y -= widget->priv->allocation.y;
+  clip_region = cairo_region_create_rectangle (&self_clip);
+
+  region2 = cairo_region_copy (region);
+  cairo_region_intersect (region2, clip_region);
+
   /* Look for the parent with a window and invalidate @region in there. */
   windowed_parent = widget;
   while (windowed_parent != NULL && !_gtk_widget_get_has_window (windowed_parent))
@@ -4457,7 +4467,6 @@ gtk_widget_queue_draw_region (GtkWidget            *widget,
   x += border.left + padding.left;
   y += border.top + padding.top;
 
-  region2 = cairo_region_copy (region);
   cairo_region_translate (region2, x, y);
 
 invalidate:
@@ -4465,6 +4474,9 @@ invalidate:
   gdk_window_invalidate_region (_gtk_widget_get_window (widget), region2, TRUE);
 
   cairo_region_destroy (region2);
+
+  if (clip_region)
+    cairo_region_destroy (clip_region);
 }